package net.simflow.swf.analyzer.fileprinter;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.TreeSet;

import net.simflow.swf.analyzer.graph.stats.data.GraphStats;
import net.simflow.swf.analyzer.network.data.Link;
import net.simflow.swf.analyzer.network.data.Node;

public class GraphStatsFilePrinter {
	private static final LinkedHashMap<String, Boolean> DEFAULT_CONFIG = new LinkedHashMap<String, Boolean>();
	static {
		DEFAULT_CONFIG.put(GraphStats.GRAPH_NAME, true);
		DEFAULT_CONFIG.put(GraphStats.DEGREE_DISTRIBUTION, true);
		DEFAULT_CONFIG.put(GraphStats.VERTICES, true);
		DEFAULT_CONFIG.put(GraphStats.EDGES, true);
	}

	private static GraphStatsFilePrinter instance = new GraphStatsFilePrinter();

	private GraphStatsFilePrinter() {
	}

	public static GraphStatsFilePrinter getInstance() {
		return instance;
	}

	public void print(FilePrinter p, GraphStats graphStats) {
		if (p == null) {
			return;
		}
		if (graphStats == null) {
			return;
		}

		p.print(FilePrinter.NEW_LINE + "Graph Info:");
		for (Entry<String, Boolean> en : DEFAULT_CONFIG.entrySet()) {
			if (!en.getValue()) {
				continue;
			}
			String title = en.getKey();
			switch (title) {
			case GraphStats.GRAPH_NAME:
				this.printNameString(p, title, graphStats);
				break;
			case GraphStats.VERTICES:
				this.printVertexNameListString(p, title, graphStats);
				break;
			case GraphStats.EDGES:
				this.printEdgeNameListString(p, title, graphStats);
				break;
			case GraphStats.DEGREE_DISTRIBUTION:
				this.printDegreeDistributionString(p, title, graphStats);
				break;
			}
		}
	}

	public void printNameString(FilePrinter p, String title, GraphStats gstats) {
		if (gstats.getGraphName() == null) {
			return;
		}
		p.print(FilePrinter.NEW_LINE + title + ":" + FilePrinter.TAB
				+ gstats.getGraphName());
	}

	public void printVertexNameListString(FilePrinter p, String title,
			GraphStats gstats) {
		if (gstats.getNodeArray() == null) {
			return;
		}

		boolean is = true;

		for (Node node : gstats.getNodeArray()) {
			if (is) {
				p.print(FilePrinter.NEW_LINE + title + ": "
						+ gstats.getNodeCount());
				is = false;
			}
			p.print(FilePrinter.TAB + node.getNameInNetwork());
		}
	}

	public void printEdgeNameListString(FilePrinter p, String title,
			GraphStats gstats) {
		if (gstats.getLinkArray() == null) {
			return;
		}

		boolean is = true;

		for (Link link : gstats.getLinkArray()) {
			if (is) {
				p.print(FilePrinter.NEW_LINE + title + ": "
						+ gstats.getLinkCount());
				is = false;
			}
			p.print(FilePrinter.TAB + link.getShortInfo());
		}
	}

	public void printDegreeDistributionString(FilePrinter p, String title,
			GraphStats gstats) {
		if (gstats.getDegreeDistribution() == null) {
			return;
		}
		gstats.getDegreeDistribution().comparator();

		boolean is = true;

		for (Entry<Integer, ArrayList<Node>> en : gstats
				.getDegreeDistribution().descendingMap().entrySet()) {
			TreeSet<String> set = new TreeSet<String>();
			for (Node node : en.getValue()) {
				set.add(node.getNameInNetwork());
			}
			set.comparator();

			if (is) {
				p.print(FilePrinter.NEW_LINE + title + ":");
				is = false;
			}
			p.print(FilePrinter.TAB + en.getKey() + " (" + en.getValue().size()
					+ "):");
			for (String s : set) {
				p.print(" " + s + ";");
			}
		}
	}
}
